﻿//==============================================================================
// File: MetaPropertyInfo.cs
// Created: 2010-05-10
// Author: Piotr Włodek
//==============================================================================
// This file is a part of MAMMOTH project.
// Copyright (C) 2010 AGH University of Science and Technology, Krakow.
// https://caribou.iisg.agh.edu.pl/trac/mammoth
//
// Mammoth is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// Mammoth is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License
// along with WpfRcp. If not, see http://www.gnu.org/licenses/.
//==============================================================================

using System;
using WpfRcp.PropertyModel.Validation;

namespace WpfRcp.PropertyModel
{
    /// <summary>
    /// Represents a information object which describes a property.
    /// </summary>
    /// <remarks>
    /// It contains the information normally stored within <see cref="MetaProperty"/> object.
    /// </remarks>
    public class MetaPropertyInfo : ValidatableBase
    {
        private string m_Name;
        private string m_DisplayName;
        private Type m_PropertyType;
        private Type m_OwnerType;
        private MetaPropertyKind m_PropertyKind;
        private bool m_ThrowsOnValidationError;
        private bool m_Matchable;

        /// <summary>
        /// Gets the name of a property.
        /// </summary>
        public string Name
        {
            get { return m_Name; }
            set
            {
                m_Name = value;
                OnPropertyChanged<MetaPropertyInfo>(t => t.Name);
            }
        }

        /// <summary>
        /// Gets or sets the display name.
        /// </summary>
        public string DisplayName
        {
            get { return m_DisplayName; }
            set
            {
                m_DisplayName = value;
                OnPropertyChanged<MetaPropertyInfo>(t => t.DisplayName);
            }
        }

        /// <summary>
        /// Gets a CLR type of a property.
        /// </summary>
        public Type PropertyType
        {
            get { return m_PropertyType; }
            set
            {
                m_PropertyType = value;
                OnPropertyChanged<MetaPropertyInfo>(t => t.PropertyType);
            }
        }

        /// <summary>
        /// Gets an owner type.
        /// </summary>
        public Type OwnerType
        {
            get { return m_OwnerType; }
            set
            {
                m_OwnerType = value;
                OnPropertyChanged<MetaPropertyInfo>(t => t.OwnerType);
            }
        }

        /// <summary>
        /// Gets a value indicating the kind of a property.
        /// </summary>
        public MetaPropertyKind PropertyKind
        {
            get { return m_PropertyKind; }
            set
            {
                m_PropertyKind = value;
                OnPropertyChanged<MetaPropertyInfo>(t => t.PropertyKind);
            }
        }

        /// <summary>
        /// Gets or sets the value indicating if the <see cref="PropertyOptions.ThrowsOnValidationError"/>
        /// has been set for this property.
        /// </summary>
        public bool ThrowsOnValidationError
        {
            get { return m_ThrowsOnValidationError; }
            set
            {
                m_ThrowsOnValidationError = value;
                OnPropertyChanged<MetaPropertyInfo>(t => t.ThrowsOnValidationError);
            }
        }

        /// <summary>
        /// Gets or sets the value indicating if the <see cref="PropertyOptions.Matchable"/>
        /// has been set for this property.
        /// </summary>
        public bool Matchable
        {
            get { return m_Matchable; }
            set
            {
                m_Matchable = value;
                OnPropertyChanged<MetaPropertyInfo>(t => t.Matchable);
            }
        }

        /// <summary>
        /// Gets a value indicating whether object is in valid state.
        /// </summary>
        public override bool IsValid
        {
            get
            {
                return !string.IsNullOrEmpty(Name) &&
                       PropertyType != null &&
                       OwnerType != null;
            }
        }

        #region Equality Implementation

        public bool Equals(MetaPropertyInfo other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return Equals(other.m_Name, m_Name) && Equals(other.m_PropertyType, m_PropertyType) && Equals(other.m_OwnerType, m_OwnerType) && Equals(other.m_PropertyKind, m_PropertyKind);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof (MetaPropertyInfo)) return false;
            return Equals((MetaPropertyInfo) obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                int result = (m_Name != null ? m_Name.GetHashCode() : 0);
                result = (result*397) ^ (m_PropertyType != null ? m_PropertyType.GetHashCode() : 0);
                result = (result*397) ^ (m_OwnerType != null ? m_OwnerType.GetHashCode() : 0);
                result = (result*397) ^ m_PropertyKind.GetHashCode();
                return result;
            }
        }

        public static bool operator ==(MetaPropertyInfo left, MetaPropertyInfo right)
        {
            return Equals(left, right);
        }

        public static bool operator !=(MetaPropertyInfo left, MetaPropertyInfo right)
        {
            return !Equals(left, right);
        }

        #endregion
    }
}